﻿namespace BEGDC.CC.Web.EZVisit
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using ASBCC.Database.Entity;
    using ASBCC.Database.Service;
    using ASBCC.Workflow.Client;
    using ASBCC.Workflow.K2Manager;
    using Utility.Extensions;

    #endregion

    public interface IEZVisitPageAccess
    {
        EZVisitAccessControl AccessControl { get; set; }
    }

    public class EZVisitAccessControl
    {
        // Set same values for both role and step.
        private const string Submission = "Submission";
        private const string AftReturnPrefix = "Post ";
        private const string EZVisitViewPermission = "EZVisit View";

        private readonly int appId;
        private readonly Step currentStep;
        private readonly bool isPDC;
        private readonly bool isCODPPManager;
        private readonly bool isFNCController;
        private readonly bool applicationRecalled;

        public EZVisitAccessControl(EmployeeTableEntity currentUser, int appId)
        {
            if (currentUser == null)
            {
                throw new ArgumentNullException("currentUser");
            }

            this.CurrentUser = currentUser;

            this.appId = appId;

            if (this.appId > 0)
            {
                this.Application = EZVisitApplicationManager.SelectByKeys(this.appId);
            }

            // New application?
            if (this.Application == null)
            {
                this.currentStep.Name = Submission;
                this.currentStep.CanDoAction = true;
            }
            else
            {
                this.currentStep.Name = string.IsNullOrEmpty(this.Application.CurrentStep) ? Submission : this.Application.CurrentStep;

                this.currentStep.IsAtAftReturnStage = this.currentStep.Name.IndexOf(AftReturnPrefix) != -1;

                string currentApprover = this.Application.CurrentApprover;

                if (currentApprover.IsNotNullOrWhiteSpace())
                {
                    this.currentStep.CanDoAction = ValueIncludes(currentApprover, currentUser.NameEN);
                }
                else if (this.Application.ProcessStatus.IsNotNullOrWhiteSpace())
                {
                    switch (this.Application.ProcessStatus)
                    {
                        case ProcessStatusConsts.Discarded:
                            this.currentStep.CanDoAction = false;
                            break;
                        case ProcessStatusConsts.End:
                            this.currentStep.IsAtAftReturnStage = true;
                            this.currentStep.CanDoAction = false;
                            break;
                    }
                }
                else
                {
                    this.currentStep.CanDoAction = true;
                }

                if (this.Application.ProcessStatus.IsNotNullOrWhiteSpace())
                {
                    this.applicationRecalled = this.Application.ProcessStatus.Equals(ProcessStatusConsts.Withdrawn);
                    this.applicationRecalled |= this.Application.ProcessStatus.Equals(ProcessStatusConsts.AskedForMore) && this.currentStep.Name.Equals(Submission);

                    this.applicationRecalled &= this.Application.CurrentApprover.Equals(this.CurrentUser.NameEN);

                    if (!this.currentStep.CanDoAction)
                    {
                        this.currentStep.CanDoAction = this.applicationRecalled;
                    }
                }

                if (this.Application.PDC.IsNotNullOrWhiteSpace())
                {
                    this.isPDC = ValueIncludes(this.Application.PDC, this.CurrentUser.NameEN);
                }

                if (this.Application.CODPPManager.IsNotNullOrWhiteSpace())
                {
                    this.isCODPPManager = ValueIncludes(this.Application.CODPPManager, this.CurrentUser.NameEN);
                }

                if (this.Application.FNCController.IsNotNullOrWhiteSpace())
                {
                    this.isFNCController = ValueIncludes(this.Application.FNCController, this.CurrentUser.NameEN);
                }
            }
        }

        public EZVisitApplicationTableEntity Application { get; private set; }

        public EmployeeTableEntity CurrentUser { get; private set; }

        public bool HasViewPermission
        {
            get
            {
                if (this.appId == 0 || this.Application == null)
                {
                    return true;
                }

                if (string.IsNullOrEmpty(this.Application.Readers))
                {
                    return this.Application.RequesterID == this.CurrentUser.EmployeeID;
                }

                string readers = this.Application.Readers;

                switch (this.Application.ProcessStatus)
                {
                    case ProcessStatusConsts.Withdrawn:
                    case ProcessStatusConsts.Discarded:
                    case ProcessStatusConsts.Rejected:
                        break;
                    default:
                        readers += GetEZVisitViewUsers();
                        break;
                }

                return ValueIncludes(readers.Trim(';'), this.CurrentUser.EmployeeID.Value.ToString());
            }
        }

        /// <summary>
        ///   Tab 1
        /// </summary>
        public TabView BasicInfoTabView
        {
            get
            {
                TabView view;

                view.Visible = false;

                if (!this.isFNCController)
                {
                    if (this.applicationRecalled || ValueIncludes(this.currentStep.Name, Submission))
                    {
                        view.Visible = !this.currentStep.CanDoAction;
                    }
                    else if (!this.isPDC)
                    {
                        view.Visible = true;
                    }
                }

                view.Editable = false;

                return view;
            }
        }

        public TabView ApplicantTabView
        {
            get
            {
                TabView view;

                view.Visible = !this.isFNCController;

                view.Editable = (this.applicationRecalled || ValueIncludes(this.currentStep.Name, Submission)) & this.currentStep.CanDoAction & !this.currentStep.IsAtAftReturnStage;

                return view;
            }
        }

        /// <summary>
        ///   Tab 2, 4, 5, 6, 10
        /// </summary>
        public TabView ApplicationTabView
        {
            get
            {
                TabView view;

                view.Visible = !this.isPDC && !this.isFNCController;

                view.Editable = (this.applicationRecalled || ValueIncludes(this.currentStep.Name, Submission)) & this.currentStep.CanDoAction & !this.currentStep.IsAtAftReturnStage;

                return view;
            }
        }

        /// <summary>
        ///   Tab 3
        /// </summary>
        public TabView ContractTabView
        {
            get
            {
                TabView view;

                view.Visible = !this.isPDC;

                view.Editable = (this.applicationRecalled || ValueIncludes(this.currentStep.Name, Submission) || ValueIncludes(this.currentStep.Name, EZVisitActivityNameConsts.FNC_Controller)) & this.currentStep.CanDoAction;

                return view;
            }
        }

        /// <summary>
        ///   Tab 7
        /// </summary>
        public TabView QuotAttchTabView
        {
            get
            {
                var view = new TabView();

                if (this.isPDC)
                {
                    view.Visible = true;
                    view.Editable = this.currentStep.CanDoAction;
                }
                else if (this.isCODPPManager)
                {
                    view.Visible = true;
                    view.Editable = this.currentStep.CanDoAction && !this.currentStep.IsAtAftReturnStage;
                }

                return view;
            }
        }

        /// <summary>
        ///   Tab 8, 9
        /// </summary>
        public TabView AftReturnTabsView
        {
            get
            {
                var view = new TabView();

                if (this.currentStep.IsAtAftReturnStage && !this.isFNCController && !isPDC)
                {
                    // Only visible when applicant updated the application.
                    view.Visible = this.Application.AftSubmitDate != null;

                    if (ValueIncludes(this.Application.CurrentApprover, this.CurrentUser.NameEN) && ValueIncludes(this.currentStep.Name, EZVisitActivityNameConsts.Post_Submission))
                    {
                        view.Visible = true;
                        view.Editable = this.currentStep.CanDoAction;
                    }
                }

                return view;
            }
        }

        public TabView CommentTabView
        {
            get
            {
                var view = new TabView();

                bool isLGDCheckPerson = ValueIncludes(this.Application.LGDCheckPerson, this.CurrentUser.NameEN);

                view.Visible = isLGDCheckPerson || ValueIncludes(this.Application.LGD, this.CurrentUser.NameEN);
                view.Editable = isLGDCheckPerson && this.currentStep.CanDoAction;

                return view;
            }
        }

        public int SelectedTab
        {
            get
            {
                if (this.currentStep.IsAtAftReturnStage)
                {
                    return this.currentStep.CanDoAction ? (this.isCODPPManager ? 8 : 7) : 0;
                }

                if (ValueIncludes(this.currentStep.Name, EZVisitActivityNameConsts.FNC_Controller))
                {
                    return this.currentStep.CanDoAction ? 2 : 0;
                }

                if (this.isPDC)
                {
                    return this.currentStep.CanDoAction ? 1 : 0;
                }

                if (!this.isPDC && ValueIncludes(this.currentStep.Name, EZVisitActivityNameConsts.COD_PP_Manager))
                {
                    return this.currentStep.CanDoAction ? 6 : 0;
                }

                return 0;
            }
        }

        private static string GetEZVisitViewUsers()
        {
            var userList = new List<int>();

            var users = K2DataHelper.GetUserInfosByROLE_CD(EZVisitViewPermission);

            string result = string.Empty;

            if (users != null && users.Count != 0)
            {
                result = users.Cast<EmployeeTableEntity>().Aggregate(result, (current, user) => current + (user.EmployeeID.Value + ";"));
            }

            return result;
        }

        private static bool ValueIncludes(string src, string dest)
        {
            src = ";" + src + ";";
            dest = ";" + dest + ";";
            return src.IndexOf(dest, StringComparison.InvariantCultureIgnoreCase) != -1;
        }

        #region Nested type: Step

        protected struct Step
        {
            public bool CanDoAction;

            public bool IsAtAftReturnStage;

            public string Name;
        }

        #endregion

        #region Nested type: TabView

        public struct TabView
        {
            public bool Visible;
            public bool Editable;
        }

        #endregion
    }
}